#include <iostream>
#include <memory>
#include <algorithm>

using std::allocator;
using std::cout;
using std::endl;
using std::uninitialized_copy;

template<typename T>
class Vector
{
public:
    /* using iterator = T *; */

    Vector();
    ~Vector();

    void push_back(const T &);      
    void pop_back();         
    int size() const;     
    int capacity() const; 
private:
    void reallocate();
    static std::allocator<T> _alloc;
    T *_start;
    T *_finish;
    T *_end_of_storage;
};

template<typename T>
std::allocator<T> Vector<T>:: _alloc;


template<typename T>
Vector<T>::Vector()
    :_start(nullptr)
     ,_finish(nullptr)
     ,_end_of_storage(nullptr)
{

}

template<typename T>
Vector<T>::~Vector()
{
    if(_start)
    {
        while(_start != _finish)
        {
            _alloc.destroy(--_finish);
        }
        _alloc.deallocate(_start,capacity());
    }
}

template<typename T>
void Vector<T>::push_back(const T &value)
{
    if(_finish == _end_of_storage)
    {
        reallocate();
    }
    if(_finish < _end_of_storage)
    {
    _alloc.construct(_finish,value);
    _finish++;
    }
}

template<typename T>
void Vector<T>::pop_back()
{
    if(size() > 0)
    {
        --_finish;
        _alloc.destroy(_finish);
    }
}

template<typename T>
int Vector<T>::size()const
{
    return _finish - _start;
}

template<typename T>
int Vector<T>::capacity()const 
{
    return _end_of_storage - _start;
}

template<typename T>
void Vector<T>::reallocate()
{
    int oldcapa = size();//int oldcapa = capacity();
    int newcapa;
    T *ptemp;
    if(oldcapa == 0)
    {
        newcapa = 1;
        ptemp = _alloc.allocate(newcapa);
    }
    else
    {
        newcapa = 2 * oldcapa;
        ptemp = _alloc.allocate(newcapa);

        /* copy(_start,_finish,ptemp); */
        uninitialized_copy(_start,_finish,ptemp);
        while(_start != _finish)
        {
            --_finish;
            _alloc.destroy(_finish);
        }
        _alloc.deallocate(_start,oldcapa);
    }
    _start = ptemp;
    _finish = ptemp + oldcapa;
    _end_of_storage = ptemp + newcapa;
}

void printVector(const Vector<int> &vec)
{
    cout << "size() = " << vec.size() << endl;
    cout << "capacity() = " << vec.capacity() << endl;
}

void test(){
     Vector<int> vec;
    printVector(vec);

    cout << endl;
    vec.push_back(1);
    printVector(vec);

    cout << endl;
    vec.push_back(2);
    printVector(vec);

    cout << endl;
    vec.push_back(3);
    printVector(vec);

    cout << endl;
    vec.push_back(4);
    printVector(vec);

    cout << endl;
    vec.push_back(5);
    printVector(vec);

/*     for(auto &elem : vec) */
/*     { */
/*         cout << elem << "  "; */
/*     } */
/*     cout << endl; */
}


int main()
{
    test();
    return 0;
}
